package com.subfg.payment.util.ali;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.subfg.common.entity.call.request.RequestPayModel;
import com.subfg.common.entity.call.request.RequestTransferModel;
import com.subfg.common.entity.call.request.refund.ApplyRefundModel;
import com.subfg.common.entity.call.result.ResultPayModel;
import com.subfg.common.entity.call.result.ResultTransferModel;
import com.subfg.common.entity.config.pay.ConfigPayAliModel;
import com.subfg.common.entity.excpetion.BusinessExceptionModel;
import com.subfg.payment.constant.DifferentSystemEnum;
import com.subfg.payment.util.ali.mode.AliPayModeServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;

/**
 * @Description 支付宝支付, 包括支付, 退款, 查询, 转账, 合并订单支付
 */
@Component
public class AliPayServer {
    private Logger log = LoggerFactory.getLogger(AliPayServer.class);

    private AlipayClient alipayClient;
    private ConfigPayAliModel configPayAli;


    @Autowired
    private AliPayModeServer aliPayModeServer;

    /**
     * 初始化支付宝支付数据
     * @param payAli
     */
    public void initAliPayInfo(ConfigPayAliModel payAli) {
        configPayAli = payAli;
        try {
            alipayClient = new DefaultAlipayClient(getAlipayConfig(payAli));
        } catch (AlipayApiException e) {
            log.info("支付宝配置失败");
            throw new RuntimeException();
        }
    }

    /**
     * 配置支付宝支付 数据
     * @param payAli
     * @return
     */
    public static AlipayConfig getAlipayConfig(ConfigPayAliModel payAli) {
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setCharset("utf-8");
        alipayConfig.setFormat("json");
        alipayConfig.setSignType("RSA2");
        alipayConfig.setAppId(payAli.getAppId());
        alipayConfig.setServerUrl(payAli.getGateway());
        alipayConfig.setPrivateKey(payAli.getPrivateKey());
        // 根据不同类型加载不同的支付宝配置类数据, 1: 密钥模式下 2:证书模式下
        if (payAli.getType() == 1) {
            alipayConfig.setAlipayPublicKey(payAli.getAlipayPublicKey());
        } else if (payAli.getType() == 2) {
            alipayConfig.setAppCertContent(payAli.getAppCertContent());
            alipayConfig.setRootCertContent(payAli.getRootCertContent());
            alipayConfig.setAlipayPublicCertContent(payAli.getAlipayPublicCertContent());
        }
        return alipayConfig;
    }

    /**
     * 创建支付宝支付方式   1: 根据不同的平台
     * @param requestPayModel
     * @return
     * @throws BusinessExceptionModel
     */
    public ResultPayModel createAlipayInfo(RequestPayModel requestPayModel) throws BusinessExceptionModel {
        ResultPayModel resultPayModel = new ResultPayModel();
        DifferentSystemEnum differentSystemEnum = DifferentSystemEnum.matchingSystem(requestPayModel.getPayPlatform());
        switch (differentSystemEnum) {
            // 生成小程序端的支付方式
            case APPLET:
                break;
            case WEB:
                //resultPayModel = aliPayModeServer.createWebPagePayInfo(requestPayModel, configPayAli, alipayClient);
                resultPayModel = aliPayModeServer.createQrcodePayInfo(requestPayModel, configPayAli, alipayClient);
                break;
            case APP:
                resultPayModel = aliPayModeServer.createAppAliPayInfo(requestPayModel, configPayAli, alipayClient);
                break;
            case QRCODE:
                resultPayModel = aliPayModeServer.createQrcodePayInfo(requestPayModel, configPayAli, alipayClient);
        }
        return resultPayModel;
    }

    /**
     * 用户使用支付宝退款
     * @param refundOrderModel  退款数据
     * @return
     * @throws BusinessExceptionModel
     */
    public ApplyRefundModel.RefundOrderModel refundAliPay(ApplyRefundModel.RefundOrderModel refundOrderModel) throws BusinessExceptionModel {
        AlipayTradeRefundResponse refundBody = aliPayModeServer.alipayRefund(refundOrderModel, configPayAli, alipayClient);
        if (refundBody == null || !refundBody.isSuccess()) {
            log.error("未知原因导致支付宝退款失败!! 支付宝方返回信息为==>>>\n{}", JSONObject.toJSONString(refundBody));
            refundOrderModel.setRefundStatus(-1);
            refundOrderModel.setExceptionExplain(JSONObject.toJSONString(refundBody));
            return refundOrderModel;
        }
        if (!refundBody.getCode().equals("10000") && !refundBody.getFundChange().equals("Y")) {
            log.error("支付宝退款调用失败!!! 支付宝方返回信息为==>>>\n{}", JSONObject.toJSONString(refundBody));
            refundOrderModel.setRefundStatus(-1);
            refundOrderModel.setExceptionExplain(JSONObject.toJSONString(refundBody));
            return refundOrderModel;
        }
        log.info("支付宝退款成功, 退款单号{}, 申请退款金额{}, 实退金额{}", refundOrderModel.getOrderNo(), refundOrderModel.getRefundAmount(), refundBody.getRefundFee());
        refundOrderModel.setRefundFeeAmount(new BigDecimal(refundBody.getRefundFee()));
        refundOrderModel.setRefundStatus(1);
        return refundOrderModel;
    }

    /**
     * 批准用户提现
     * @param requestTransferModel
     * @return
     * @throws BusinessExceptionModel
     */
    public ResultTransferModel transferAffirm(RequestTransferModel requestTransferModel) throws BusinessExceptionModel {
        AlipayFundTransUniTransferResponse transferBody = aliPayModeServer.aliTransfer(requestTransferModel, configPayAli, alipayClient);
        if (transferBody == null || !transferBody.isSuccess()) {
            log.error("未知原因导致支付宝提现失败!! 支付宝返回错误信息如下: ==>>>\n{}", JSONObject.toJSONString(transferBody));
            throw new BusinessExceptionModel();
        }
        if (!transferBody.getStatus().equals("SUCCESS")) {
            log.error("支付宝退款调用提现失败, 支付宝返回信息为==>>>{}", JSONObject.toJSONString(transferBody));
        }
        return new ResultTransferModel().builder()
                .transferNo(transferBody.getOutBizNo())
                .channelNo(transferBody.getOrderId())
                .amount(requestTransferModel.getTransferAmount())
                .build();
    }




}
